package com.crazymaker.demo.hystrix;

import com.crazymaker.springcloud.demo.api.UAAUserApi;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandMetrics;
import feign.Feign;
import feign.Target;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
import org.springframework.cloud.openfeign.support.SpringMvcContract;

import java.math.BigInteger;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 测试HystrixCommand
 */
@Slf4j
public class HttpGetterCommand extends HystrixCommand<String> {

    private String url;

    // 是否运行run
    private boolean hasRun = false;

    // 执行次序
    private int index;

    private Class<?> clazz;

    // 总的调用次数，线程安全
    private static AtomicInteger total = new AtomicInteger(0);

    // 失败调用次数，线程安全
    private static AtomicInteger failed = new AtomicInteger(0);

    public HttpGetterCommand(String url, Setter setter) {
        super(setter);
        this.url = url;
    }

    public HttpGetterCommand(Class<?> clazz, Setter setter) {
        super(setter);
        this.clazz = clazz;
    }

    @Override
    protected String run() throws Exception {
        hasRun = true;
        index = total.getAndIncrement();
        log.info("req:{} -> start", index);
        // 执行url请求
        String responseData = "";
        if (this.clazz != null) {
            UAAUserApi userApi = Feign.builder()
                    .contract(new SpringMvcContract())
                    .target(new Target.HardCodedTarget<>(UAAUserApi.class, "http://localhost:7703/uaa-provider"));
            responseData = userApi.getUser(BigInteger.valueOf(2)).getBody().toString();
        } else {
            responseData = this.url;
        }
        Thread.sleep(1000);
        log.info("req:{} -> end:{}", index, responseData);
        return "req" + index + ":" + responseData;
    }

    @Override
    protected String getFallback() {
        boolean isFastFailed = !hasRun;
        if (isFastFailed) {
            // 直接失败，都没有经过run方法
            index = total.getAndIncrement();
        }
        // 是否熔断
        if (super.isCircuitBreakerOpen()) {
            // 成功次数
            HystrixCommandMetrics.HealthCounts counts = super.getMetrics().getHealthCounts();
            log.info("window totalRequests:{}, errorPercentage:{}", counts.getTotalRequests(), counts.getErrorPercentage());
        }
        boolean isOpen = super.isCircuitBreakerOpen();
        log.info("req:{}, 熔断:{}, 直接失败:{}, 失败请求次数:{}", index, isOpen, isFastFailed, failed.getAndIncrement());
        return "req" + index + ":调用失败";
    }
}
